package com.ruoyi.consumer.controller.facilit;

import ch.qos.logback.classic.Logger;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ijpay.core.kit.WxPayKit;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.consumer.controller.facilit.api.APIService;
import com.ruoyi.consumer.controller.facilit.fill.FillService;
import com.ruoyi.consumer.controller.wallet.WalletService;
import com.ruoyi.consumer.controller.wallet.walletOperationFactory.DeductionService;
import com.ruoyi.consumer.domain.*;
import com.ruoyi.consumer.domain.order.PayOrder;
import com.ruoyi.consumer.domain.order.PayOrderDTO;
import com.ruoyi.consumer.service.impl.CFillingFacilitServiceImpl;
import com.ruoyi.consumer.service.impl.CUserServiceImpl;
import com.ruoyi.consumer.service.impl.CWalletCompanyServiceImpl;
import com.ruoyi.consumer.service.impl.CWalletPersonServiceImpl;
import com.ruoyi.consumer.utils.JsonUtils;
import com.ruoyi.consumer.utils.StreamUtils;
import com.ruoyi.consumer.utils.pay.HttpRequest;
import com.ruoyi.web.controller.tool.QRTool;
import io.jsonwebtoken.lang.Assert;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;

import static com.ruoyi.consumer.constance.ApiConstance.URL_PREFIX;

/**
 * @author: YFENTEST
 * @ date : 2023/11/23
 * @description:
 */
@Api(tags = "加注机")
@RestController
@RequestMapping("/api/Filer")
public class FilerController {
    private static final Logger logger = (Logger) LoggerFactory.getLogger(JsonUtils.class);


    //    测试用的设备号
    private static final String num = "202107100009";

    @Autowired
    private WxConfig wxConfig;

    @Autowired
    private CFillingFacilitServiceImpl fillingFacilitService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private APIService apiService;

    @Autowired
    private WalletService walletService;

    @Autowired
    private FillService fillService;

    @Autowired
    private QRTool qrTool;

    @Autowired
    private CUserServiceImpl userService;

    @Autowired
    private DeductionService deductionService;

    @Autowired
    private CWalletPersonServiceImpl walletPersonService;

    @Autowired
    private CWalletCompanyServiceImpl walletCompanyService;

    @ApiOperation("获取机器token")
    @GetMapping("/get-token")
    public String getToken(@ApiParam("appKey") String appKey,
                           @ApiParam("用户id") String appSecret) {
        return apiService.getAuthorization(appKey, appSecret);
    }

    //根据id获取sn
    public String getSnById(Integer id) {
        CFillingFacilit cFillingFacilit = fillingFacilitService.selectCFillingFacilitByFacilitId(id);
        Assert.notNull(cFillingFacilit, "加注机不存在");
        return cFillingFacilit.getFacilitSn();
    }

    @ApiOperation("获取机器详情信息")
    @GetMapping("/get-equipmentInfoBySn")
    public AjaxResult getEquipmentInfoBySn(@ApiParam("加注机id") Integer sn) throws IOException {
        String SN = getSnById(sn);
        String token = redisCache.getCacheObject("token:" + "authorizerAccessToken");
        System.out.println(token);
        String s = apiService.getEquipmentInfoBySn(SN, token);
        if (s == null || s.isEmpty() || s == "") {
            String params = "appKey=" + wxConfig.getZLappKey() + "&appSecret=" + wxConfig.getZLappSecret();
            String sr = HttpRequest.sendGet(URL_PREFIX + "oauth/authorize", params);
            JSONObject json = JSONObject.parseObject(sr);
            JSONObject datas = json.getJSONObject("datas");
            // 提取 authorization 的值
            String authorization = datas.getString("authorization");
            System.out.println("Access Token: " + authorization);
            redisCache.setCacheObject("token:" + "authorizerAccessToken", authorization);
            System.out.println("=======重新获取token");
            token = authorization;
            String ss = apiService.getEquipmentInfoBySn(SN, token);
            Map<String, Object> manage = null;
            Map<String, Object> heartbeat = null;
            try {
                String jsonString = ss; // 您的 JSON 字符串

                ObjectMapper mapper = new ObjectMapper();

                // 解析 JSON 字符串为 Map
                Map<String, Object> jsonMap = mapper.readValue(jsonString, Map.class);

                // 获取 datas 对象
                Map<String, Object> data = (Map<String, Object>) jsonMap.get("datas");

                // 获取 manage 对象
                if (datas != null) {
                    manage = (Map<String, Object>) data.get("manage");
                    heartbeat = (Map<String, Object>) data.get("heartbeat");

                    // 现在 manage 包含您需要的信息
                    System.out.println(manage);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            AjaxResult ajaxResult = AjaxResult.success();
            ajaxResult.put("manage", manage);
            ajaxResult.put("heartbeat", heartbeat);
            CFillingFacilit cFillingFacilit = fillingFacilitService.selectCFillingFacilitByFacilitId(sn);
            Assert.notNull(cFillingFacilit, "加注机不存在");
            ajaxResult.put("cFillingFacilit", cFillingFacilit);
            return AjaxResult.success(ajaxResult);
        }


        Map<String, Object> manage = null;
        Map<String, Object> heartbeat = null;
        try {
            String jsonString = s; // 您的 JSON 字符串

            ObjectMapper mapper = new ObjectMapper();

            // 解析 JSON 字符串为 Map
            Map<String, Object> jsonMap = mapper.readValue(jsonString, Map.class);

            // 获取 datas 对象
            Map<String, Object> datas = (Map<String, Object>) jsonMap.get("datas");

            // 获取 manage 对象
            if (datas != null) {
                manage = (Map<String, Object>) datas.get("manage");
                heartbeat = (Map<String, Object>) datas.get("heartbeat");

                // 现在 manage 包含您需要的信息
                System.out.println(manage);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        AjaxResult ajaxResult = AjaxResult.success();
        ajaxResult.put("manage", manage);
        ajaxResult.put("heartbeat", heartbeat);
        CFillingFacilit cFillingFacilit = fillingFacilitService.selectCFillingFacilitByFacilitId(sn);
        Assert.notNull(cFillingFacilit, "加注机不存在");
        ajaxResult.put("cFillingFacilit", cFillingFacilit);
        return AjaxResult.success(ajaxResult);
    }

    @ApiOperation("获取库位信息")
    @GetMapping("/get-equipmentStockBySn")
    public String getEquipmentStockBySn(@ApiParam("加注机id") Integer sn) throws IOException {
        String SN = getSnById(sn);
        String token = redisCache.getCacheObject("token:" + "authorizerAccessToken");
        System.out.println(token);
        return apiService.getEquipmentStockBySn(SN, token);
    }

    @ApiOperation("总订单查询接口")
    @GetMapping("/get-orderByOrderId")
    public String getOrderByOrderId(@ApiParam("OrderId") Long orderId) throws IOException {
        String token = redisCache.getCacheObject("token:" + "authorizerAccessToken");
        System.out.println(token);
        return apiService.findByOrderId(orderId, token);
    }

    @ApiOperation("前端持续小订单查询接口")
    @GetMapping("/get-orderDetailByOrderId")
    public String getDetailByOrderId(@ApiParam("OrderId") Long orderId) throws IOException {
        String token = redisCache.getCacheObject("token:" + "authorizerAccessToken");
        if (redisCache.getCacheObject("orderStatus:" + orderId) == "加注结束") {
            return "加注结束";
        }
        System.out.println(token);
        return apiService.findOrderDetailByOrderId(orderId, token);
    }

    @ApiOperation("后端小订单查询接口")
    @GetMapping("/get-minOrder")
    public String getMinOrder(@ApiParam("OrderId") Long orderId,
                              @ApiParam("out_trade_no") String out_trade_no) throws IOException {
        return fillService.minOrder(orderId, out_trade_no);
    }


    //扫码支付加注回调接口
    @ApiOperation("扫码支付加注回调接口")
    @PostMapping("/payCallback")
    public void rechargePersonWalletCallback(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ServletInputStream inputStream = request.getInputStream();
        String notifyXml = StreamUtils.inputStream2String(inputStream, "utf-8");
        if (!notifyXml.isEmpty()) {
            fillService.payFillNotice(notifyXml);
            walletService.responseToWeixin(response, notifyXml);
        } else {
            walletService.responseToWeixin(response, "");
        }
        Map<String, String> stringStringMap = WxPayKit.xmlToMap(notifyXml);
        logger.info("微信支付回调响应");
        logger.info("是否成功:" + stringStringMap.get("out_trade_no"));
        logger.info("微信支付回调成功");
    }

    //前端回调拿到订单id
    @ApiOperation("前端回调拿到订单id")
    @GetMapping("/getOrderId")
    public AjaxResult getOrderId(@ApiParam("out_trade_no") String out_trade_no) {
        Integer orderId = redisCache.getCacheObject("fillOrderId:" + out_trade_no);
        return AjaxResult.success(orderId);
    }


    @ApiOperation("测试下单接口")
    @PostMapping("/takeOrder")
    public String takeOrder(@RequestBody PayOrder payOrder) {
        String token = redisCache.getCacheObject("token:" + "authorizerAccessToken");

        //构建传给机器的订单信息
        PayOrderDTO payOrderDTO = new PayOrderDTO();
        payOrderDTO.setEquipmentName("银河一号机");
        payOrderDTO.setSn("5cbf26ac31f44ba899f27f78bd016341");
        payOrderDTO.setOrderVol(50.00);
        payOrderDTO.setOrderPrice(2.000);
        payOrderDTO.setOrderMoney(100.00);
        payOrderDTO.setOrderTitle("测试小订单");
        payOrderDTO.setOrderType(2);
        payOrderDTO.setCreateTime(new Date());
        payOrderDTO.setSnNumber(num);
        System.out.println("==========下单信息========");
        System.out.println(payOrderDTO);
        System.out.println("==========下单信息========");
        return apiService.payOrder(payOrderDTO, token);
    }


    //生成机器码
    @ApiOperation("添加加注机")
    @GetMapping("/add-machine")
    public AjaxResult addMachine(@ApiParam(value = "加注机名", required = true) String name,
                                 @ApiParam(value = "加注机sn", required = true) String sn) {
        CFillingFacilit cFillingFacilit = new CFillingFacilit();
        cFillingFacilit.setFacilitSn(sn);
        List<CFillingFacilit> cFillingFacilits1 = fillingFacilitService.selectCFillingFacilitList(cFillingFacilit);
        if (!cFillingFacilits1.isEmpty()) {
            return AjaxResult.error("该加注机已存在");
        }
        cFillingFacilit.setFacilitName(name);
        int i = fillingFacilitService.insertCFillingFacilit(cFillingFacilit);
        if (i > 0) {
            CFillingFacilit cFillingFacilitNoFacImg = new CFillingFacilit();
            cFillingFacilitNoFacImg.setFacilitId(cFillingFacilit.getFacilitId());
            cFillingFacilitNoFacImg.setFacilitSn(sn);

            String s = qrTool.SnGenerate(sn, "sn", String.valueOf(cFillingFacilit.getFacilitId()));
            cFillingFacilitNoFacImg.setFacilitImg(s);
            cFillingFacilitNoFacImg.setStatus(3);
            fillingFacilitService.updateCFillingFacilit(cFillingFacilitNoFacImg);

            CFillingFacilit cFillingFacilit1 = fillingFacilitService.selectCFillingFacilitByFacilitId(cFillingFacilitNoFacImg.getFacilitId());
            return AjaxResult.success(cFillingFacilit1);
        } else {
            return AjaxResult.error("添加失败");
        }
    }

    //钱包下单逻辑（工厂模式）
    @PostMapping("/deductBalance")
    public AjaxResult deductBalance(@ApiParam(value = "用户openId", required = true) String openId,
                                    @ApiParam(value = "加注量", required = true) Long amount,
                                    @ApiParam(value = "记住机id", required = true) Integer facilitId,
                                    @ApiParam(value = "snNumber", required = true) String snNumber,
                                    @ApiParam(value = "下单类型", required = true) String userType) throws IOException {

        CUser cUser = new CUser();
        cUser.setOpenid(openId);
        List<CUser> cUsers = userService.selectCUserList(cUser);
        if (cUsers.isEmpty()) {
            return AjaxResult.error("用户不存在");
        }
        Integer userId = cUsers.get(0).getUserId();
        return AjaxResult.success(deductionService.takeOrder(userId, facilitId, amount, userType, snNumber));
    }

    //获取钱包加注小订单（工厂模式）
    @PostMapping("/getMinOrderForWallet")
    public AjaxResult getMinOrderForWallet(@ApiParam(value = "用户id", required = true) Long orderId,
                                           @ApiParam(value = "下单类型", required = true) String userType) throws IOException {
        return AjaxResult.success(deductionService.getMinOrder(orderId, userType));
    }

    //查询钱包余量
    @GetMapping("/getBalance")
    public AjaxResult getBalance(@ApiParam(value = "userId", required = true) Integer userId,
                                 @ApiParam(value = "下单类型:1个人钱包加注,2公司钱包加注", required = true) Integer fillType) {
        Assert.notNull(userId, "userId不能为空");
        Assert.notNull(fillType, "下单类型不能为空");

        //查询用户信息
        CUser cUser = userService.selectCUserByUserId(userId);
        Assert.notNull(cUser, "用户不存在");

        Integer walletId = null;
        if (fillType == 1) {
            walletId = cUser.getUserId();
            CWalletPerson cWalletPerson = walletPersonService.selectCWalletPersonByUserId(walletId);
            Assert.notNull(cWalletPerson, "个人钱包不存在");
            return AjaxResult.success(cWalletPerson.getWalletFree());
        } else if (fillType == 2) {
            walletId = cUser.getCompanyId();
            CWalletCompany cWalletCompany = walletCompanyService.selectCWalletCompanyByWalletPersonId(walletId);
            Assert.notNull(cWalletCompany, "公司钱包不存在");
            return AjaxResult.success(cWalletCompany.getWalletFree());
        } else {
            return AjaxResult.error("下单类型错误");
        }
    }

}
